<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 6.3.0">
  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png">
  <link rel="mask-icon" href="/images/logo.svg" color="#222">

<link rel="stylesheet" href="/css/main.css">


<link rel="stylesheet" href="/lib/font-awesome/css/all.min.css">

<script id="hexo-configurations">
    var NexT = window.NexT || {};
    var CONFIG = {"hostname":"chuangges.gitee.io","root":"/","scheme":"Pisces","version":"7.8.0","exturl":false,"sidebar":{"position":"right","display":"post","padding":18,"offset":12,"onmobile":false},"copycode":{"enable":true,"show_result":true,"style":"mac"},"back2top":{"enable":true,"sidebar":false,"scrollpercent":false},"bookmark":{"enable":false,"color":"#222","save":"auto"},"fancybox":false,"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"algolia":{"hits":{"per_page":10},"labels":{"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}},"localsearch":{"enable":false,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false},"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},"path":"search.xml"};
  </script>

  <meta name="description" content="React Hooks、组件复用、性能优化">
<meta property="og:type" content="article">
<meta property="og:title" content="React 工具库">
<meta property="og:url" content="https://chuangges.gitee.io/2019/08/29/10-2-React%E5%B7%A5%E5%85%B7%E5%BA%93/index.html">
<meta property="og:site_name" content="闯哥要去流浪了">
<meta property="og:description" content="React Hooks、组件复用、性能优化">
<meta property="og:locale" content="zh_CN">
<meta property="article:published_time" content="2019-08-29T06:27:28.000Z">
<meta property="article:modified_time" content="2023-12-01T11:11:36.127Z">
<meta property="article:author" content="chuangges">
<meta property="article:tag" content="JS 框架">
<meta name="twitter:card" content="summary">

<link rel="canonical" href="https://chuangges.gitee.io/2019/08/29/10-2-React%E5%B7%A5%E5%85%B7%E5%BA%93/">


<script id="page-configurations">
  // https://hexo.io/docs/variables.html
  CONFIG.page = {
    sidebar: "",
    isHome : false,
    isPost : true,
    lang   : 'zh-CN'
  };
</script>

  <title>React 工具库 | 闯哥要去流浪了</title>
  






  <noscript>
  <style>
  .use-motion .brand,
  .use-motion .menu-item,
  .sidebar-inner,
  .use-motion .post-block,
  .use-motion .pagination,
  .use-motion .comments,
  .use-motion .post-header,
  .use-motion .post-body,
  .use-motion .collection-header { opacity: initial; }

  .use-motion .site-title,
  .use-motion .site-subtitle {
    opacity: initial;
    top: initial;
  }

  .use-motion .logo-line-before i { left: initial; }
  .use-motion .logo-line-after i { right: initial; }
  </style>
</noscript>

<link rel="alternate" href="/atom.xml" title="闯哥要去流浪了" type="application/atom+xml">
</head>

<body itemscope itemtype="http://schema.org/WebPage">
  <div class="container use-motion">
    <div class="headband"></div>

    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏">
      <span class="toggle-line toggle-line-first"></span>
      <span class="toggle-line toggle-line-middle"></span>
      <span class="toggle-line toggle-line-last"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/" class="brand" rel="start">
      <span class="logo-line-before"><i></i></span>
      <h1 class="site-title">闯哥要去流浪了</h1>
      <span class="logo-line-after"><i></i></span>
    </a>
      <p class="site-subtitle" itemprop="description">愿你岁月可回首，且以深情共白头</p>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
    </div>
  </div>
</div>




<nav class="site-nav">
  <ul id="menu" class="main-menu menu">
        <li class="menu-item menu-item-home">

    <a href="/" rel="section"><i class="fa fa-home fa-fw"></i>首页</a>

  </li>
        <li class="menu-item menu-item-tags">

    <a href="/tags/" rel="section"><i class="fa fa-tags fa-fw"></i>标签</a>

  </li>
        <li class="menu-item menu-item-categories">

    <a href="/categories/" rel="section"><i class="fa fa-th fa-fw"></i>分类</a>

  </li>
        <li class="menu-item menu-item-archives">

    <a href="/archives/" rel="section"><i class="fa fa-archive fa-fw"></i>归档</a>

  </li>
  </ul>
</nav>




</div>
    </header>

    
  <div class="back-to-top">
    <i class="fa fa-arrow-up"></i>
    <span>0%</span>
  </div>
  <div class="reading-progress-bar"></div>


    <main class="main">
      <div class="main-inner">
        <div class="content-wrap">
          

          <div class="content post posts-expand">
            

    
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="https://chuangges.gitee.io/2019/08/29/10-2-React%E5%B7%A5%E5%85%B7%E5%BA%93/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/chuang.png">
      <meta itemprop="name" content="chuangges">
      <meta itemprop="description" content="chuangge's blog.">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="闯哥要去流浪了">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          React 工具库
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2019-08-29 14:27:28" itemprop="dateCreated datePublished" datetime="2019-08-29T14:27:28+08:00">2019-08-29</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2023-12-01 19:11:36" itemprop="dateModified" datetime="2023-12-01T19:11:36+08:00">2023-12-01</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/JS-%E6%A1%86%E6%9E%B6/" itemprop="url" rel="index"><span itemprop="name">JS 框架</span></a>
                </span>
            </span>

          <br>
            <span class="post-meta-item" title="本文字数">
              <span class="post-meta-item-icon">
                <i class="far fa-file-word"></i>
              </span>
                <span class="post-meta-item-text">本文字数：</span>
              <span>17k</span>
            </span>
            <span class="post-meta-item" title="阅读时长">
              <span class="post-meta-item-icon">
                <i class="far fa-clock"></i>
              </span>
                <span class="post-meta-item-text">阅读时长 &asymp;</span>
              <span>15 分钟</span>
            </span>
            <div class="post-description">React Hooks、组件复用、性能优化</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
        <h1 id="一、React-Hooks"><a href="#一、React-Hooks" class="headerlink" title="一、React Hooks"></a>一、React Hooks</h1><h2 id="数据更新驱动"><a href="#数据更新驱动" class="headerlink" title="数据更新驱动"></a>数据更新驱动</h2>  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/** </span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> useState：初始化时执行一次，返回初始值和更新函数。</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> useReducer：用于在函数组件中运行 redux 类似功能。</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> useSyncExternalStore：concurrent 模式读取第三方状态库等外部数据源。</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> useTransition：对更新渲染进行降级，先渲染优先级高的更新，实现性能优化。</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> useDeferredValue：将原更新进行推迟渲染，避开紧急任务的渲染，实现节流。</span></span><br><span class="line"><span class="comment">**/</span></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">React</span>, &#123; useState, useEffect, useRef, useContext &#125; <span class="keyword">from</span> <span class="string">&#x27;react&#x27;</span></span><br><span class="line"><span class="keyword">const</span> <span class="title function_">Demo</span> = (<span class="params">&#123; a &#125;</span>) =&gt; &#123;</span><br><span class="line">    <span class="keyword">const</span> <span class="title function_">handleResize</span> =(<span class="params"></span>)=&gt;&#123; &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 状态初始值、状态更新函数</span></span><br><span class="line">    <span class="keyword">const</span> [number, setNumber] = <span class="title function_">useState</span>(<span class="number">0</span>)</span><br><span class="line">    </span><br><span class="line">    <span class="comment">// 默认执行函数、函数执行条件</span></span><br><span class="line">    <span class="title function_">useEffect</span>(() = &#123;</span><br><span class="line">        <span class="variable language_">document</span>.<span class="property">title</span> = <span class="string">`<span class="subst">$&#123;number&#125;</span> times`</span>;</span><br><span class="line">    &#125;, [])    <span class="comment">// 空数组：组件挂载/首次渲染时执行</span></span><br><span class="line">    <span class="title function_">useEffect</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">        <span class="title function_">getUserInfo</span>(a).<span class="title function_">then</span>(<span class="function"><span class="params">res</span>=&gt;</span>&#123;</span><br><span class="line">            <span class="title function_">setUserMessage</span>(res)</span><br><span class="line">        &#125;)</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 订阅、计时器的设置和卸载</span></span><br><span class="line">        <span class="variable language_">window</span>.<span class="title function_">addEventListener</span>(<span class="string">&#x27;resize&#x27;</span>, handleResize)</span><br><span class="line">        <span class="keyword">const</span> timer = <span class="built_in">setInterval</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">            <span class="title function_">setNumber</span>(number + <span class="number">1</span>)</span><br><span class="line">        &#125;, <span class="number">1000</span>)</span><br><span class="line">        <span class="variable language_">window</span>.<span class="title function_">addEventListener</span>(<span class="string">&#x27;resize&#x27;</span>, handleResize)</span><br><span class="line"></span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">function</span> (<span class="params"></span>) &#123;</span><br><span class="line">            <span class="built_in">clearInterval</span>(timer) </span><br><span class="line">            <span class="variable language_">window</span>.<span class="title function_">removeEventListener</span>(<span class="string">&#x27;resize&#x27;</span>, handleResize)</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;, [a, number])   <span class="comment">// a、number 变量更新时执行</span></span><br><span class="line">    <span class="keyword">return</span> <span class="language-xml"><span class="tag">&lt;<span class="name">button</span> <span class="attr">onClick</span>=<span class="string">&#123;()</span>=&gt;</span> setNumber(number + 1)&#125;&gt;点击<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 错误写法</span></span><br><span class="line">    <span class="title function_">useEffect</span>(<span class="keyword">async</span> ()=&gt;&#123;</span><br><span class="line">        <span class="keyword">const</span> res = <span class="keyword">await</span> <span class="title function_">getUserInfo</span>(payload)</span><br><span class="line">    &#125;, [])</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="title function_">DemoUseReducer</span> = (<span class="params"></span>)=&gt;&#123;</span><br><span class="line">    <span class="comment">// 新 state、派发函数 = 更新函数 reducer、初始 state</span></span><br><span class="line">    <span class="keyword">const</span> [number, dispatchNum] = <span class="title function_">useReducer</span>(<span class="function">(<span class="params">state, action</span>)=&gt;</span>&#123;</span><br><span class="line">        <span class="keyword">const</span> &#123; payload, name &#125; = action</span><br><span class="line">        <span class="keyword">switch</span> (name) &#123;</span><br><span class="line">            <span class="keyword">case</span> <span class="string">&#x27;add&#x27;</span>:</span><br><span class="line">                <span class="keyword">return</span> state + <span class="number">1</span></span><br><span class="line">            <span class="keyword">case</span> <span class="string">&#x27;sub&#x27;</span>:</span><br><span class="line">                <span class="keyword">return</span> state - <span class="number">1</span> </span><br><span class="line">            <span class="keyword">case</span> <span class="string">&#x27;reset&#x27;</span>:</span><br><span class="line">                <span class="keyword">return</span> payload       </span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> state</span><br><span class="line">    &#125;, <span class="number">0</span>)</span><br><span class="line">    <span class="keyword">return</span> <span class="language-xml"><span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">        当前值：&#123; number &#125;</span></span><br><span class="line"><span class="language-xml">        <span class="tag">&lt;<span class="name">button</span> <span class="attr">onClick</span>=<span class="string">&#123;()</span>=&gt;</span>dispatchNum(&#123; name:&#x27;add&#x27; &#125;)&#125;&gt;增加<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">        <span class="tag">&lt;<span class="name">button</span> <span class="attr">onClick</span>=<span class="string">&#123;()</span>=&gt;</span>dispatchNum(&#123; name:&#x27;sub&#x27; &#125;)&#125;&gt;减少<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">        <span class="tag">&lt;<span class="name">button</span> <span class="attr">onClick</span>=<span class="string">&#123;()</span>=&gt;</span>dispatchNum(&#123; name:&#x27;reset&#x27;, payload: 66 &#125;)&#125;</span></span><br><span class="line"><span class="language-xml">        &gt;赋值<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">        <span class="tag">&lt;<span class="name">MyChildren</span> <span class="attr">dispatch</span>=<span class="string">&#123;</span> <span class="attr">dispatchNum</span> &#125; <span class="attr">State</span>=<span class="string">&#123;&#123;</span> <span class="attr">number</span> &#125;&#125; /&gt;</span></span></span><br><span class="line"><span class="language-xml">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">function</span> <span class="title function_">App</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="keyword">const</span> subscribe = <span class="keyword">function</span> (<span class="params">callback</span>) &#123;</span><br><span class="line">        <span class="variable language_">window</span>.<span class="title function_">addEventListener</span>(<span class="string">&quot;online&quot;</span>, callback);</span><br><span class="line">        <span class="variable language_">window</span>.<span class="title function_">addEventListener</span>(<span class="string">&quot;offline&quot;</span>, callback);</span><br><span class="line">        <span class="keyword">return</span> <span class="function">() =&gt;</span> &#123;</span><br><span class="line">            <span class="variable language_">window</span>.<span class="title function_">removeEventListener</span>(<span class="string">&quot;online&quot;</span>, callback);</span><br><span class="line">            <span class="variable language_">window</span>.<span class="title function_">removeEventListener</span>(<span class="string">&quot;offline&quot;</span>, callback);</span><br><span class="line">        &#125;;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 状态更新的订阅函数、返回新状态的更新函数、hydration 模式的更新函数</span></span><br><span class="line">    <span class="keyword">const</span> isOnline = <span class="title function_">useSyncExternalStore</span>(</span><br><span class="line">        subscribe, </span><br><span class="line">        <span class="function">() =&gt;</span> navigator.<span class="property">onLine</span>,</span><br><span class="line">        <span class="function">() =&gt;</span> <span class="literal">true</span></span><br><span class="line">    )</span><br><span class="line">    <span class="keyword">return</span> (<span class="language-xml"><span class="tag">&lt;&gt;</span>网络状态：&#123;isOnline.toString()&#125;<span class="tag">&lt;/&gt;</span></span>)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// 过渡状态 isPending: true 过渡中 false 结束、执行的过渡任务</span></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">React</span>, &#123; useState, useTransition &#125; <span class="keyword">from</span> <span class="string">&#x27;react&#x27;</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">const</span> <span class="title function_">App</span> = (<span class="params"></span>) =&gt; &#123;</span><br><span class="line">    <span class="keyword">let</span> [count, setCount] = <span class="title function_">useState</span>(<span class="number">100</span>)</span><br><span class="line">    <span class="keyword">let</span> [isPending, startTransition] = <span class="title function_">useTransition</span>()</span><br><span class="line">    <span class="keyword">const</span> <span class="title function_">addCount</span> = (<span class="params"></span>) =&gt; &#123;</span><br><span class="line">        <span class="title function_">startTransition</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">            <span class="title function_">setCount</span>(<span class="function"><span class="params">v</span> =&gt;</span> v + <span class="number">1</span>)</span><br><span class="line">        &#125;)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> (</span><br><span class="line">        <span class="language-xml"><span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;<span class="name">h3</span>&gt;</span>&#123;isPending ? &#x27;加载中...&#x27; : count&#125;<span class="tag">&lt;/<span class="name">h3</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;<span class="name">button</span> <span class="attr">onClick</span>=<span class="string">&#123;addCount&#125;</span>&gt;</span>增加<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">        <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line">    )</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="title function_">Search</span> = (<span class="params">&#123; kw &#125;</span>) =&gt; &#123;</span><br><span class="line">    <span class="keyword">const</span> data = <span class="title class_">Array</span>(<span class="number">1000</span>).<span class="title function_">fill</span>(<span class="string">&#x27;&#x27;</span>).<span class="title function_">map</span>(<span class="function">(<span class="params">_, index</span>) =&gt;</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="string">&#x27;搜索 -- &#x27;</span> + index + <span class="string">&#x27; -- &#x27;</span> + kw</span><br><span class="line">    &#125;)</span><br><span class="line">    <span class="keyword">return</span> (<span class="language-xml"><span class="tag">&lt;<span class="name">ul</span>&gt;</span>&#123;data.map(item =&gt; (<span class="tag">&lt;<span class="name">li</span> <span class="attr">key</span>=<span class="string">&#123;item&#125;</span>&gt;</span>&#123;item&#125;<span class="tag">&lt;/<span class="name">li</span>&gt;</span>))&#125;<span class="tag">&lt;/<span class="name">ul</span>&gt;</span></span>)</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">const</span> <span class="title function_">App</span> = (<span class="params"></span>) =&gt; &#123;</span><br><span class="line">    <span class="keyword">let</span> [kw, setKw] = <span class="title function_">useState</span>(<span class="string">&#x27;&#x27;</span>)</span><br><span class="line">    <span class="keyword">let</span> deferredValue = <span class="title function_">useDeferredValue</span>(kw)</span><br><span class="line">    <span class="keyword">return</span> (<span class="language-xml"><span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">        <span class="tag">&lt;<span class="name">h3</span>&gt;</span>&#123;kw&#125;<span class="tag">&lt;/<span class="name">h3</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">        <span class="tag">&lt;<span class="name">input</span> <span class="attr">value</span>=<span class="string">&#123;kw&#125;</span> <span class="attr">onChange</span>=<span class="string">&#123;e</span>=&gt;</span> setKw(e.target.value.trim())&#125; /&gt;</span></span><br><span class="line"><span class="language-xml">        <span class="tag">&lt;<span class="name">Search</span> <span class="attr">kw</span>=<span class="string">&#123;deferredValue&#125;</span> /&gt;</span></span></span><br><span class="line"><span class="language-xml">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span>)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="执行副作用"><a href="#执行副作用" class="headerlink" title="执行副作用"></a>执行副作用</h2>  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@title</span> 副作用指新增监听器和日志等，主作用则指通过 state/props 渲染组件。</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> useEffect：组件渲染后异步执行，不阻塞渲染但回调修改 DOM 会重绘。</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> useLayoutEffect：浏览器绘制前同步执行，回调修改 DOM 会阻塞渲染。</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> useInsertionEffect：元素插入到 DOM 时执行，主要用于 DOM 操作。</span></span><br><span class="line"><span class="comment">**/</span></span><br><span class="line"><span class="keyword">const</span> <span class="title function_">DemoUseLayoutEffect</span> = (<span class="params"></span>) =&gt; &#123;</span><br><span class="line">    <span class="keyword">const</span> target = <span class="title function_">useRef</span>()</span><br><span class="line">    <span class="title function_">useLayoutEffect</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">        <span class="comment">// dom 绘制前移动到指定位置</span></span><br><span class="line">        <span class="keyword">const</span> &#123; x ,y &#125; = <span class="title function_">getPositon</span>()</span><br><span class="line">        <span class="title function_">animate</span>(target.<span class="property">current</span>, &#123; x,y &#125;)</span><br><span class="line">    &#125;, []);</span><br><span class="line">    <span class="title function_">useInsertionEffect</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">        <span class="comment">// 元素插入前操作：滚动到顶部、动画效果</span></span><br><span class="line">        <span class="variable language_">window</span>.<span class="title function_">scrollTo</span>(<span class="number">0</span>, <span class="number">0</span>);</span><br><span class="line">        target.<span class="property">current</span>.<span class="property">classList</span>.<span class="title function_">add</span>(<span class="string">&#x27;fade-in&#x27;</span>);</span><br><span class="line">    &#125;)</span><br><span class="line">    <span class="title function_">useInsertionEffect</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">        <span class="comment">// 滚动时按需加载内容，返回函数中移除了监听来避免内存泄漏</span></span><br><span class="line">        <span class="keyword">const</span> <span class="title function_">handleScroll</span> = (<span class="params"></span>) =&gt; &#123;</span><br><span class="line">            <span class="keyword">const</span> scrollPosition = <span class="variable language_">window</span>.<span class="property">innerHeight</span> + <span class="variable language_">window</span>.<span class="property">scrollY</span>;</span><br><span class="line">            <span class="keyword">const</span> documentHeight = <span class="variable language_">document</span>.<span class="property">body</span>.<span class="property">offsetHeight</span>;</span><br><span class="line">            <span class="keyword">if</span> (scrollPosition &gt;= documentHeight) &#123;</span><br><span class="line">                <span class="comment">// 加载更多内容</span></span><br><span class="line">            &#125;</span><br><span class="line">        &#125;;</span><br><span class="line">        <span class="variable language_">window</span>.<span class="title function_">addEventListener</span>(<span class="string">&#x27;scroll&#x27;</span>, handleScroll);</span><br><span class="line">        <span class="keyword">return</span> <span class="function">() =&gt;</span> <span class="variable language_">window</span>.<span class="title function_">removeEventListener</span>(<span class="string">&#x27;scroll&#x27;</span>, handleScroll)</span><br><span class="line">    &#125;)</span><br><span class="line">    <span class="keyword">return</span> (<span class="language-xml"><span class="tag">&lt;<span class="name">span</span> <span class="attr">ref</span>=<span class="string">&#123;target&#125;</span> <span class="attr">className</span>=<span class="string">&quot;animate&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">span</span>&gt;</span></span>))</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


<h2 id="状态获取与传递"><a href="#状态获取与传递" class="headerlink" title="状态获取与传递"></a>状态获取与传递</h2>  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> useContext：用于跨组件层级直接传递数据，可取代 Context.Consumer。</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> useRef：用于在 current 属性上获取元素和保存数据，但不会触发组件更新。</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> useImperativeHandle：可配合 forwardRef 向父组件自定义暴露出实例。</span></span><br><span class="line"><span class="comment">**/</span></span><br><span class="line"><span class="keyword">const</span> <span class="title class_">Context</span> = <span class="title function_">createContext</span>()</span><br><span class="line"><span class="keyword">const</span> <span class="title function_">DemoContext</span> = (<span class="params"></span>)=&gt; &#123;</span><br><span class="line">    <span class="keyword">const</span> <span class="attr">count</span>:any = <span class="title function_">useContext</span>(<span class="title class_">Context</span>)</span><br><span class="line">    <span class="keyword">return</span> <span class="language-xml"><span class="tag">&lt;<span class="name">div</span>&gt;</span>useContext 方式：点击次数为 &#123;count&#125;<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">const</span> <span class="title function_">DemoConsumer</span> = (<span class="params"></span>)=&gt;&#123;</span><br><span class="line">    <span class="keyword">return</span> (</span><br><span class="line">        <span class="language-xml"><span class="tag">&lt;<span class="name">Context.Consumer</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            &#123;count=&gt; <span class="tag">&lt;<span class="name">div</span>&gt;</span>Consumer 方式：点击次数为 &#123;count&#125;<span class="tag">&lt;/<span class="name">div</span>&gt;</span> &#125;</span></span><br><span class="line"><span class="language-xml">        <span class="tag">&lt;/<span class="name">Context.Consumer</span>&gt;</span></span></span><br><span class="line">    )</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> ()=&gt;&#123;</span><br><span class="line">    <span class="keyword">const</span> [count, setCount] = <span class="title function_">useState</span>(<span class="number">0</span>);</span><br><span class="line">    <span class="keyword">return</span> (</span><br><span class="line">        <span class="language-xml"><span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;<span class="name">Button</span> <span class="attr">onClick</span>=<span class="string">&#123;()</span>=&gt;</span>setCount(count+1)&#125;&gt;点击<span class="tag">&lt;/<span class="name">Button</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;<span class="name">Context.Provider</span> <span class="attr">value</span>=<span class="string">&#123;count&#125;</span> &gt;</span></span></span><br><span class="line"><span class="language-xml">                <span class="tag">&lt;<span class="name">DemoContext</span> /&gt;</span></span></span><br><span class="line"><span class="language-xml">                <span class="tag">&lt;<span class="name">DemoConsumer</span> /&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;/<span class="name">Context.Provider</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">        <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line">    )</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="title function_">DemoUseRef</span> = (<span class="params"></span>)=&gt;&#123;</span><br><span class="line">    <span class="keyword">const</span> btn = <span class="title function_">useRef</span>(<span class="literal">null</span>)</span><br><span class="line">    <span class="keyword">const</span> sta = <span class="title function_">useRef</span>(<span class="literal">false</span>)</span><br><span class="line">    <span class="keyword">const</span> <span class="title function_">onSubmit</span> = (<span class="params"></span>) =&gt; &#123;</span><br><span class="line">        <span class="keyword">let</span> btnDom = btn.<span class="property">current</span></span><br><span class="line">        div.<span class="property">current</span> = <span class="literal">true</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="language-xml"><span class="tag">&lt;<span class="name">button</span> <span class="attr">ref</span>=<span class="string">&#123;btn&#125;</span> <span class="attr">onClick</span>=<span class="string">&#123;()</span> =&gt;</span> onSubmit()&#125;&gt;提交<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// 自动聚焦功能</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">Home</span>(<span class="params">props, appRef</span>) &#123;</span><br><span class="line">    <span class="keyword">const</span> inputRef = <span class="title function_">useRef</span>();</span><br><span class="line">    <span class="title function_">useImperativeHandle</span>(appRef, <span class="function">() =&gt;</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> &#123;</span><br><span class="line">            <span class="attr">myFocus</span>: <span class="function">() =&gt;</span> &#123;</span><br><span class="line">                inputRef.<span class="property">current</span>.<span class="title function_">focus</span>();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;);</span><br><span class="line">    <span class="keyword">return</span> <span class="language-xml"><span class="tag">&lt;<span class="name">input</span> <span class="attr">ref</span>=<span class="string">&#123;inputRef&#125;</span> <span class="attr">type</span>=<span class="string">&quot;text&quot;</span> /&gt;</span></span></span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">const</span> <span class="title class_">ForwardHome</span> = <span class="title function_">forwardRef</span>(<span class="title class_">Home</span>);</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">function</span> <span class="title function_">App</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="keyword">const</span> appRef = <span class="title function_">useRef</span>();</span><br><span class="line">    <span class="keyword">function</span> <span class="title function_">btnClick</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="comment">// useImperativeHandle 没有时可直接操作元素</span></span><br><span class="line">        appRef.<span class="property">current</span>.<span class="title function_">focus</span>();</span><br><span class="line">        appRef.<span class="property">current</span>.<span class="property">value</span> = <span class="string">&#x27;北京&#x27;</span>;</span><br><span class="line">        <span class="comment">// useImperativeHandle 添加自定义权限：回调会返回允许操作</span></span><br><span class="line">        appRef.<span class="property">current</span>.<span class="title function_">myFocus</span>();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> (</span><br><span class="line">        <span class="language-xml"><span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;<span class="name">ForwardHome</span> <span class="attr">ref</span>=<span class="string">&#123;appRef&#125;/</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;<span class="name">button</span> <span class="attr">onClick</span>=<span class="string">&#123;()</span> =&gt;</span> &#123; btnClick() &#125;&#125;&gt;获取<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">        <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line">    )</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="状态派生与保存"><a href="#状态派生与保存" class="headerlink" title="状态派生与保存"></a>状态派生与保存</h2>  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> useMemo：指定依赖项变化时才执行渲染逻辑，减少渲染时的逻辑计算。</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> useCallback：父组件传递的 props 每次更新时都会触发子组件更新，</span></span><br><span class="line"><span class="comment"> * 此时可配合 memo / pureComponent 实现的具有浅比较优化功能(比较 props </span></span><br><span class="line"><span class="comment"> * 发现未更新时就不会重新渲染)的组件来提升性能，其它场景则不建议使用。</span></span><br><span class="line"><span class="comment">**/</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Child</span> <span class="keyword">extends</span> <span class="title class_ inherited__">React.PureComponent</span> &#123;    </span><br><span class="line">    <span class="title function_">render</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="language-xml"><span class="tag">&lt;<span class="name">button</span> <span class="attr">onClick</span>=<span class="string">&#123;this.props.onClick&#125;</span>&gt;</span>初始<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">const</span> <span class="title class_">Child</span> = <span class="title class_">React</span>.<span class="title function_">memo</span>(<span class="keyword">function</span> (<span class="params">&#123; count, onClick &#125;: any</span>) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="language-xml"><span class="tag">&lt;<span class="name">button</span> <span class="attr">onClick</span>=<span class="string">&#123;onClick&#125;</span>&gt;</span>初始：&#123;count&#125;<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span></span><br><span class="line">&#125;)</span><br><span class="line"><span class="keyword">function</span> <span class="title function_">DemoMemo</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="keyword">const</span> [val, setVal] = <span class="title function_">useState</span>(<span class="string">&#x27;&#x27;</span>);</span><br><span class="line">    <span class="keyword">const</span> [count, setCount] = <span class="title function_">useState</span>(<span class="number">0</span>);</span><br><span class="line">    <span class="comment">// val 更新时重新渲染组件 DemoMemo，但不会重新执行 getNum</span></span><br><span class="line">    <span class="keyword">const</span> getNum = <span class="title function_">useMemo</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="title class_">Array</span>.<span class="title function_">from</span>(&#123;<span class="attr">length</span>: count * <span class="number">100</span>&#125;, <span class="function">(<span class="params">v, i</span>) =&gt;</span> i)</span><br><span class="line">        .<span class="title function_">reduce</span>(<span class="function">(<span class="params">a, b</span>) =&gt;</span> a + b)</span><br><span class="line">    &#125;, [count])</span><br><span class="line"></span><br><span class="line">    <span class="comment">// val 更新时不会重新渲染组件 Child</span></span><br><span class="line">    <span class="keyword">const</span> onInitCount = <span class="title function_">useCallback</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">        <span class="title function_">setCount</span>(<span class="number">1</span>)</span><br><span class="line">    &#125;, [count])</span><br><span class="line">    <span class="keyword">return</span> (</span><br><span class="line">        <span class="language-xml"><span class="tag">&lt;&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;<span class="name">span</span>&gt;</span>总和：&#123;getNum()&#125;<span class="tag">&lt;/<span class="name">span</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;<span class="name">div</span> <span class="attr">onClick</span>=<span class="string">&#123;()</span> =&gt;</span> setCount(count + 1)&#125;&gt;点击<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;<span class="name">input</span> <span class="attr">value</span>=<span class="string">&#123;val&#125;</span> <span class="attr">onChange</span>=<span class="string">&#123;e</span>=&gt;</span>setVal(e.target.value)&#125; /&gt;</span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;<span class="name">Child</span> <span class="attr">count</span>=<span class="string">&#123;count&#125;</span> <span class="attr">onClick</span>=<span class="string">&#123;onInitCount&#125;</span> /&gt;</span></span></span><br><span class="line"><span class="language-xml">        <span class="tag">&lt;/&gt;</span></span></span><br><span class="line">    );</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


<h2 id="开发调试工具"><a href="#开发调试工具" class="headerlink" title="开发调试工具"></a>开发调试工具</h2>  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> useId：服务器渲染时在服务端和客户端生成唯一 id，解决不一致的问题。</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> useDebugValue：只能用于自定义 hook，开发者工具调试时会显示标签。</span></span><br><span class="line"><span class="comment">**/</span> </span><br><span class="line"><span class="keyword">const</span> id = <span class="title function_">useId</span>();</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> &#123;useCallback, useDebugValue, useEffect, useState&#125; <span class="keyword">from</span> <span class="string">&quot;react&quot;</span>;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> <span class="title function_">useFetch</span> = (<span class="params">url: string</span>) =&gt; &#123; </span><br><span class="line">    <span class="keyword">const</span> [response, setResponse] = useState&lt;any&gt;(); </span><br><span class="line">    <span class="keyword">const</span> [status, setStatus] = useState&lt;boolean&gt;(<span class="literal">false</span>); </span><br><span class="line">    <span class="keyword">const</span> [error, setError] = useState&lt;any&gt;();</span><br><span class="line"></span><br><span class="line">    <span class="title function_">useDebugValue</span>(<span class="string">&#x27;Success State of API Call: &#x27;</span> + status); </span><br><span class="line">    <span class="title function_">useDebugValue</span>(<span class="string">&#x27;Error State of API Call: &#x27;</span> + error); </span><br><span class="line">    <span class="title function_">useDebugValue</span>(<span class="string">&#x27;Data Returned From API Call: &#x27;</span> + response);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">const</span> getData = <span class="title function_">useCallback</span>(<span class="keyword">async</span> () =&gt; &#123; </span><br><span class="line">        <span class="keyword">try</span> &#123; </span><br><span class="line">            <span class="keyword">const</span> res = <span class="keyword">await</span> <span class="title function_">fetch</span>(url, &#123; </span><br><span class="line">                <span class="attr">method</span>: <span class="string">&#x27;GET&#x27;</span>, </span><br><span class="line">                <span class="attr">mode</span>: <span class="string">&#x27;cors&#x27;</span>, </span><br><span class="line">                <span class="attr">headers</span>: &#123; <span class="string">&#x27;Content-Type&#x27;</span>: <span class="string">&#x27;application/json&#x27;</span> &#125; </span><br><span class="line">            &#125;); </span><br><span class="line">            <span class="keyword">const</span> data = <span class="keyword">await</span> res.<span class="title function_">json</span>(); </span><br><span class="line">            <span class="title function_">setResponse</span>(data); </span><br><span class="line">            <span class="title function_">setStatus</span>(data.<span class="property">success</span>); </span><br><span class="line">        &#125; <span class="keyword">catch</span> (err) &#123; </span><br><span class="line">            <span class="title function_">setError</span>(err); </span><br><span class="line">        &#125; </span><br><span class="line">    &#125;, [url]);</span><br><span class="line"></span><br><span class="line">    <span class="title function_">useEffect</span>(<span class="function">() =&gt;</span> &#123; </span><br><span class="line">      <span class="title function_">getData</span>(); </span><br><span class="line">    &#125;, [getData, url]);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> &#123; response, error &#125;;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="自定义-Hook"><a href="#自定义-Hook" class="headerlink" title="自定义 Hook"></a>自定义 Hook</h2>  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; useState, useEffect &#125; <span class="keyword">from</span> <span class="string">&#x27;react&#x27;</span>;</span><br><span class="line"><span class="keyword">import</span> axios <span class="keyword">from</span> <span class="string">&#x27;axios&#x27;</span>;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">function</span> <span class="title function_">useAxios</span>(<span class="params">url</span>) &#123;</span><br><span class="line">    <span class="keyword">const</span> [loading, setLoading] = <span class="title function_">useState</span>(<span class="literal">false</span>);</span><br><span class="line">    <span class="keyword">const</span> [data, setData] = <span class="title function_">useState</span>()</span><br><span class="line">    <span class="keyword">const</span> [error, setError] = <span class="title function_">useState</span>()</span><br><span class="line">    <span class="title function_">useEffect</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">        <span class="title function_">setLoading</span>(<span class="literal">true</span>)</span><br><span class="line">        axios.<span class="title function_">get</span>(url)</span><br><span class="line">            .<span class="title function_">then</span>(<span class="function"><span class="params">res</span> =&gt;</span> <span class="title function_">setData</span>(res))</span><br><span class="line">            .<span class="title function_">catch</span>(<span class="function"><span class="params">error</span> =&gt;</span> <span class="title function_">setError</span>(error))</span><br><span class="line">            .<span class="title function_">finally</span>(<span class="function">() =&gt;</span> &#123;<span class="title function_">setLoading</span>(<span class="literal">false</span>)&#125;)</span><br><span class="line">    &#125;, [url])</span><br><span class="line">    <span class="keyword">return</span> [loading, data, error]</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 组件使用</span></span><br><span class="line"><span class="keyword">import</span> useAxios <span class="keyword">from</span> <span class="string">&#x27;./UseAxios&#x27;</span>;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> () =&gt; &#123;</span><br><span class="line">    <span class="keyword">const</span> url = <span class="string">&#x27;http://localhost:3000/&#x27;</span>;</span><br><span class="line">    <span class="keyword">const</span> [loading, data, error] = <span class="title function_">useAxios</span>(url) </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


<h1 id="二、组件复用方案"><a href="#二、组件复用方案" class="headerlink" title="二、组件复用方案"></a>二、组件复用方案</h1><h2 id="Mixin-混入"><a href="#Mixin-混入" class="headerlink" title="Mixin 混入"></a>Mixin 混入</h2><blockquote>
<p>CreateClass 创建组件时拷贝公共逻辑，存在命名冲突和耦合问题而已弃用。</p>
</blockquote>
  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> <span class="title class_">MyCom</span> = <span class="title class_">React</span>.<span class="title function_">createClass</span>(&#123;   </span><br><span class="line">    <span class="attr">mixins</span>: [&#123;</span><br><span class="line">        <span class="attr">log</span>: <span class="keyword">function</span>(<span class="params"></span>) &#123; <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="number">11</span>)  &#125;</span><br><span class="line">    &#125;],</span><br><span class="line">    <span class="title function_">render</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> (<span class="language-xml"><span class="tag">&lt;<span class="name">button</span> <span class="attr">onClick</span>=<span class="string">&#123;this.log&#125;</span>&gt;</span>打印<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span>)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>


<h2 id="HOC-高阶组件"><a href="#HOC-高阶组件" class="headerlink" title="HOC 高阶组件"></a>HOC 高阶组件</h2><blockquote>
<p>一个接收可复用组件为参数并返回新组件的纯函数，可看作是 React 对装饰器模式的一种实现，它降低了父子组件的耦合度但存在 <code>静态构建</code>(新组件的生命周期只在渲染时执行而不会立即执行)、难以溯源的<code>嵌套地狱</code>等问题。具体实现时可通过 <code>属性代理</code>(创建新组件来包裹作为子组件的原组件) 和 <code>反向继承</code>(创建新组件来继承作为父组件的原组件)，常见的应用场景有 <code>复用代码</code>、<code>强化 props</code> (混入新属性 withRouter)、<strong>扩展组件</strong> (keepaliveLifeCycle 新增组件事件和生命周期)、<strong>控制渲染</strong> (react-redux&#x2F;connect dva&#x2F;dynamic 懒加载和条件渲染等)。</p>
</blockquote>
  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 属性代理</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">function</span> <span class="title function_">withMouse</span>(<span class="params">WrappedCom</span>) &#123;</span><br><span class="line">    <span class="keyword">class</span> <span class="title class_">Mouse</span> <span class="keyword">extends</span> <span class="title class_ inherited__">React.Component</span> &#123;</span><br><span class="line">        state =&#123; <span class="attr">x</span>: <span class="number">0</span>, <span class="attr">y</span>: <span class="number">0</span> &#125;</span><br><span class="line">        handleMouseMove = <span class="function"><span class="params">e</span> =&gt;</span> &#123;</span><br><span class="line">            <span class="variable language_">this</span>.<span class="title function_">setState</span>(&#123; <span class="attr">x</span>: e.<span class="property">clientx</span>, <span class="attr">y</span>: e.<span class="property">clienty</span> &#125;)</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="title function_">componentDidMount</span>(<span class="params"></span>) &#123;</span><br><span class="line">            <span class="variable language_">window</span>.<span class="title function_">addEventListener</span>(<span class="string">&#x27;mousemove&#x27;</span>, <span class="variable language_">this</span>.<span class="property">handleMouseMove</span>)</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="title function_">componentWillUnmount</span>(<span class="params"></span>) &#123;</span><br><span class="line">            <span class="variable language_">window</span>.<span class="title function_">removeEventListener</span>(<span class="string">&#x27;mousemove&#x27;</span>, <span class="variable language_">this</span>.<span class="property">handleMouseMove</span>)</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="title function_">render</span>(<span class="params"></span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="language-xml"><span class="tag">&lt;<span class="name">WrappedCom</span> &#123;<span class="attr">...this.state</span>&#125; &#123;<span class="attr">...this.props</span>&#125; /&gt;</span></span> </span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="title class_">Mouse</span>.<span class="property">displayName</span> = <span class="string">`WithMouse<span class="subst">$&#123;getDisplayName(WrappedCom)&#125;</span>`</span><span class="comment">// 组件名</span></span><br><span class="line">    <span class="keyword">return</span> <span class="title class_">Mouse</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">function</span> <span class="title function_">getDidplayName</span>(<span class="params">WrappedCom</span>) &#123;  </span><br><span class="line">    <span class="keyword">return</span> <span class="title class_">WrappedCom</span>.<span class="property">getDidplayName</span> || <span class="title class_">WrappedCom</span>.<span class="property">name</span> || <span class="string">&#x27;Component&#x27;</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">@<span class="title function_">withMouse</span>(<span class="string">&quot;组件内获取高阶组件定义的 Props&quot;</span>)</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">class</span> <span class="title class_">Demo</span> <span class="keyword">extends</span> <span class="title class_ inherited__">Component</span> &#123;</span><br><span class="line">    <span class="title function_">render</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> (<span class="language-xml"><span class="tag">&lt;<span class="name">div</span>&gt;</span>鼠标位置：&#123;props.x&#125;, &#123;props.y&#125;<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;   </span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// 反向继承</span></span><br><span class="line"><span class="keyword">const</span> <span class="title function_">ReverHOC</span> = <span class="title class_">WrapComponent</span> =&gt; &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">class</span> <span class="title class_">extends</span> <span class="title class_">WrapComponent</span> &#123;</span><br><span class="line">        <span class="title function_">constructor</span>(<span class="params">props</span>) &#123;</span><br><span class="line">            <span class="variable language_">super</span>(props)</span><br><span class="line">            <span class="variable language_">this</span>.<span class="property">state</span> = &#123; <span class="attr">count</span>: <span class="number">100</span> &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="title function_">componentDidMount</span>(<span class="params"></span>) &#123;</span><br><span class="line">            <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;原组件的属性和状态&quot;</span>, <span class="variable language_">this</span>.<span class="property">props</span>, <span class="variable language_">this</span>.<span class="property">state</span>)</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="title function_">render</span>(<span class="params"></span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> (</span><br><span class="line">                <span class="language-xml"><span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">                    <span class="tag">&lt;<span class="name">div</span> <span class="attr">onClick</span>=<span class="string">&#123;this.clickCom&#125;</span>&gt;</span>触发原组件的事件<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">                    <span class="tag">&lt;<span class="name">div</span>&gt;</span>渲染父组件不可使用其标签：&#123;super.render()&#125;<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">                <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line">            )</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">ChildComponent</span> <span class="keyword">extends</span> <span class="title class_ inherited__">React.Component</span> &#123;</span><br><span class="line">    <span class="title function_">constructor</span>(<span class="params">props</span>) &#123;</span><br><span class="line">        <span class="variable language_">super</span>(props)</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">state</span> = &#123; <span class="attr">count</span>: <span class="number">999</span> &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="title function_">clickComponent</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;组件被点了&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="title function_">render</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> (<span class="language-xml"><span class="tag">&lt;<span class="name">div</span>&gt;</span>&#123;this.state.count&#125;<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span>)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">const</span> <span class="title class_">HOCView</span> = <span class="title class_">ReverHOC</span>(<span class="title class_">ChildComponent</span>)</span><br><span class="line"><span class="keyword">let</span> <span class="title function_">demo</span> = (<span class="params"></span>) =&gt; &#123;</span><br><span class="line">    <span class="keyword">return</span> (</span><br><span class="line">        <span class="language-xml"><span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;<span class="name">ChildComponent</span> /&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;<span class="name">HOCView</span> /&gt;</span></span></span><br><span class="line"><span class="language-xml">        <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line">    )</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="Render-Props"><a href="#Render-Props" class="headerlink" title="Render Props"></a>Render Props</h2><blockquote>
<p>父组件通过 props 将返回新组件的渲染函数传递给子组件，优点有动态构建、没有命名冲突、父子传递而可溯源，但也存在使用繁琐、没有组件上下文而无法获取子组件实例等问题。</p>
</blockquote>
  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Mouse</span> <span class="keyword">extends</span> <span class="title class_ inherited__">React.Component</span> &#123;</span><br><span class="line">    <span class="title function_">constructor</span>(<span class="params">props</span>) &#123;</span><br><span class="line">        <span class="variable language_">super</span>(props);</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">state</span> = &#123; <span class="attr">x</span>: <span class="number">0</span>,  <span class="attr">y</span>: <span class="number">0</span>, &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    handleMove = <span class="function"><span class="params">e</span> =&gt;</span> &#123;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="title function_">setState</span>(&#123; <span class="attr">x</span>: e.<span class="property">clientX</span>, <span class="attr">y</span>: e.<span class="property">clientY</span> &#125;)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="title function_">componentDidMount</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="variable language_">window</span>.<span class="title function_">addEventListener</span>(<span class="string">&#x27;mousemove&#x27;</span>, <span class="variable language_">this</span>.<span class="property">handleMove</span>)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="title function_">componentWillUnmount</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="variable language_">window</span>.<span class="title function_">removeEventListener</span>(<span class="string">&#x27;mousemove&#x27;</span>, <span class="variable language_">this</span>.<span class="property">handleMove</span>)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="title function_">render</span>(<span class="params"></span>) &#123;  </span><br><span class="line">        <span class="comment">// 暴露出子组件数据，可使用任意名称的 prop</span></span><br><span class="line">        <span class="keyword">return</span> <span class="variable language_">this</span>.<span class="property">props</span>.<span class="title function_">render</span>(<span class="variable language_">this</span>.<span class="property">state</span>)</span><br><span class="line">        <span class="keyword">return</span> <span class="variable language_">this</span>.<span class="property">props</span>.<span class="title function_">chlidren</span>(<span class="variable language_">this</span>.<span class="property">state</span>)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="title class_">Mouse</span>.<span class="property">prototypes</span> = &#123;    <span class="comment">// props 校验</span></span><br><span class="line">    <span class="attr">render</span>: <span class="title class_">PropTypes</span>.<span class="property">func</span>.<span class="property">isRequired</span>,</span><br><span class="line">    <span class="attr">children</span>: <span class="title class_">PropTypes</span>.<span class="property">func</span>.<span class="property">isRequired</span>,</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">App</span> <span class="keyword">extends</span> <span class="title class_ inherited__">React.Component</span> &#123;</span><br><span class="line">    <span class="title function_">render</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> (</span><br><span class="line">            <span class="language-xml"><span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">                <span class="tag">&lt;<span class="name">span</span>&gt;</span>render 接收数据<span class="tag">&lt;/<span class="name">span</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">                <span class="tag">&lt;<span class="name">Mouse</span> <span class="attr">render</span>=<span class="string">&#123;</span> <span class="attr">props</span> =&gt;</span> &#123; </span></span><br><span class="line"><span class="language-xml">                    return (<span class="tag">&lt;<span class="name">p</span>&gt;</span>&#123;props.x&#125;, &#123;props.y&#125;<span class="tag">&lt;/<span class="name">p</span>&gt;</span>)</span></span><br><span class="line"><span class="language-xml">                &#125;&#125;&gt;<span class="tag">&lt;/<span class="name">Mouse</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">                <span class="tag">&lt;<span class="name">span</span>&gt;</span>children 接收数据<span class="tag">&lt;/<span class="name">span</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">                <span class="tag">&lt;<span class="name">Mouse</span>&gt;</span>&#123; (props) =&gt; &#123;</span></span><br><span class="line"><span class="language-xml">                    return (<span class="tag">&lt;<span class="name">p</span>&gt;</span>&#123;props.x&#125;, &#123;props.y&#125;<span class="tag">&lt;/<span class="name">p</span>&gt;</span>)</span></span><br><span class="line"><span class="language-xml">                &#125;&#125;<span class="tag">&lt;/<span class="name">Mouse</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line">        )</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


<h2 id="React-Hooks"><a href="#React-Hooks" class="headerlink" title="React Hooks"></a>React Hooks</h2><blockquote>
<p>React16.8 为函数组件实现状态处理和生命周期等功能而引入的钩子函数，解决了嵌套地狱问题和类组件存在的 this 指向容易错误、生命周期的逻辑代码难以维护、代码复用成本高等问题，但也存在不能用于循环&#x2F;条件判断&#x2F;嵌套函数、闭包场景可能获取到旧状态等缺陷。使用规则有：前缀名必须是 use、只能用于函数组件、不支持生命周期、只能在函数最外层调用。</p>
</blockquote>
<ul>
<li>数据更新驱动：useState 组件内部数据、useSyncExternalStore 外部数据源、useReducer 订阅更新、useTransition 过渡更新、useDeferredValue 延迟更新。</li>
<li>执行副作用：useEffect 异步、useLayoutEffect 同步、useInsertionEffect css-in-js。</li>
<li>状态获取与传递：useContext 上下文、useRef 元素、useImperativeHandle 组件实例。</li>
<li>状态派生与保存：useMemo 新状态、useCallback 新渲染函数。</li>
<li>工具类型：useId 服务端渲染、useDebugValue 开发调试。</li>
</ul>
<h1 id="三、组件性能优化"><a href="#三、组件性能优化" class="headerlink" title="三、组件性能优化"></a>三、组件性能优化</h1><ul>
<li><strong>useMemo 缓存计算</strong>：组件每次重新渲染时只有参数变化时才会重新计算新结果。</li>
<li><strong>useCallback 缓存方法</strong>：缓存一个回调函数并只在指定依赖项变化时重新创建。</li>
<li><strong>Reac.memo 缓存组件</strong>：只有传入状态值变化时才重新渲染，否则返回缓存组件。</li>
<li><strong>React.PureComponent 浅比较</strong>：父组件状态更新时比较子组件用到的新旧状态。</li>
<li><strong>React.Component shouldComponentUpdate</strong>：常用于手动比较组件新旧状态。</li>
<li><strong>React.lazy 组件懒加载 + Suspense 加载效果</strong>：加快页面响应而提高用户体验。</li>
<li><strong>React.Fragment</strong>：返回多个元素而不需要添加额外的根节点，减少额外节点的渲染。</li>
<li><strong>key 提升循环列表的渲染性能</strong>：React 只对新旧 key 对比后的变化部分进行更新。</li>
<li><strong>避免使用内联对象和匿名函数</strong>：组件每次重新渲染时新建其引用并将其看作不同对象。</li>
<li><strong>react-loadable + IntersectionObserver</strong>：按需加载并监听图像和列表的可见性。 </li>
<li><strong>React-virtualized &#x2F; React-window 虚拟列表</strong>：只是渲染可见区域的元素。</li>
<li><strong>交互式导入资源</strong>：触发某些操作时才去加载相关的组件或依赖包，避免阻塞主线程。</li>
<li><strong>Web-Worker</strong>：创建多线程的环境，主线程把计算密集型或高延迟的任务分配给后者。</li>
</ul>
  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">class</span> <span class="title class_">MyCom</span> <span class="keyword">extends</span> <span class="title class_ inherited__">React.Component</span> &#123;</span><br><span class="line">    <span class="title function_">constructor</span>(<span class="params">props</span>) &#123;</span><br><span class="line">        <span class="variable language_">super</span>(props)</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">state</span> = &#123; <span class="attr">count</span>: <span class="number">0</span>, <span class="attr">name</span>: <span class="string">&#x27;小花&#x27;</span> &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="title function_">shouldComponentUpdate</span>(<span class="params">nextProps, nextState</span>) &#123;</span><br><span class="line">        <span class="keyword">if</span> (nextState.<span class="property">count</span> === <span class="variable language_">this</span>.<span class="property">state</span>.<span class="property">count</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">false</span>;  <span class="comment">// 不重新渲染</span></span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">true</span>;       <span class="comment">// 重新渲染</span></span><br><span class="line">    &#125;</span><br><span class="line">    changeName = <span class="function">() =&gt;</span> &#123;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="title function_">setState</span>(&#123;<span class="attr">name</span>: <span class="variable language_">this</span>.<span class="property">state</span>.<span class="property">name</span> + <span class="string">&#x27;-&#x27;</span>&#125;)</span><br><span class="line">    &#125;</span><br><span class="line">    changeCount = <span class="function">() =&gt;</span> &#123;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="title function_">setState</span>(&#123;<span class="attr">count</span>: <span class="variable language_">this</span>.<span class="property">state</span>.<span class="property">count</span> + <span class="number">1</span>&#125;)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="title function_">render</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="language-xml"><span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;<span class="name">p</span>&gt;</span>count: &#123;this.state.count&#125;<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;<span class="name">p</span>&gt;</span>name: &#123;this.state.name&#125;<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;<span class="name">button</span> <span class="attr">onClick</span>=<span class="string">&#123;this.changeCount&#125;</span>&gt;</span>数字<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;<span class="name">button</span> <span class="attr">onClick</span>=<span class="string">&#123;this.changeName&#125;</span>&gt;</span>名称<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">        <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// 懒加载</span></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">React</span>, &#123; lazy, <span class="title class_">Suspense</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;react&#x27;</span>;</span><br><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">BrowserRouter</span> <span class="keyword">as</span> <span class="title class_">Router</span>, <span class="title class_">Route</span>, <span class="title class_">Switch</span> &#125; </span><br><span class="line"><span class="keyword">from</span> <span class="string">&#x27;react-router-dom&#x27;</span>;</span><br><span class="line"><span class="keyword">const</span> <span class="title class_">Home</span> = <span class="title function_">lazy</span>(<span class="function">() =&gt;</span> <span class="title function_">import</span>(<span class="string">&#x27;./Home&#x27;</span>));</span><br><span class="line"><span class="keyword">const</span> <span class="title class_">About</span> = <span class="title function_">lazy</span>(<span class="function">() =&gt;</span> <span class="title function_">import</span>(<span class="string">&#x27;./About&#x27;</span>));</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">function</span> <span class="title function_">App</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="keyword">return</span> (</span><br><span class="line">        <span class="language-xml"><span class="tag">&lt;<span class="name">Router</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;<span class="name">Suspense</span> <span class="attr">fallback</span>=<span class="string">&#123;</span>&lt;<span class="attr">div</span>&gt;</span>Loading...<span class="tag">&lt;/<span class="name">div</span>&gt;</span>&#125;&gt;</span></span><br><span class="line"><span class="language-xml">                <span class="tag">&lt;<span class="name">Switch</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">                    <span class="tag">&lt;<span class="name">Route</span> <span class="attr">exact</span> <span class="attr">path</span>=<span class="string">&quot;/&quot;</span> <span class="attr">component</span>=<span class="string">&#123;Home&#125;</span> /&gt;</span></span></span><br><span class="line"><span class="language-xml">                    <span class="tag">&lt;<span class="name">Route</span> <span class="attr">path</span>=<span class="string">&quot;/about&quot;</span> <span class="attr">component</span>=<span class="string">&#123;About&#125;</span> /&gt;</span></span></span><br><span class="line"><span class="language-xml">                <span class="tag">&lt;/<span class="name">Switch</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;/<span class="name">Suspense</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">        <span class="tag">&lt;/<span class="name">Router</span>&gt;</span></span></span><br><span class="line">    );</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// Fragment</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">TdList</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="keyword">return</span> (</span><br><span class="line">        <span class="language-xml"><span class="tag">&lt;<span class="name">React.Fragment</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;<span class="name">span</span>&gt;</span>Hello<span class="tag">&lt;/<span class="name">span</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;<span class="name">span</span>&gt;</span>World<span class="tag">&lt;/<span class="name">span</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">        <span class="tag">&lt;/<span class="name">React.Fragment</span>&gt;</span></span></span><br><span class="line">    );</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// key 提升性能</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">MyCom</span>(<span class="params">props</span>) &#123;</span><br><span class="line">    <span class="keyword">const</span> data = props.<span class="property">data</span>;</span><br><span class="line">    <span class="keyword">return</span> (</span><br><span class="line">        <span class="language-xml"><span class="tag">&lt;<span class="name">ul</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            &#123;data.map(item =&gt; <span class="tag">&lt;<span class="name">li</span> <span class="attr">key</span>=<span class="string">&#123;item.id&#125;</span>&gt;</span>&#123;item.name&#125;<span class="tag">&lt;/<span class="name">li</span>&gt;</span>)&#125;</span></span><br><span class="line"><span class="language-xml">        <span class="tag">&lt;/<span class="name">ul</span>&gt;</span></span></span><br><span class="line">    );</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 避免匿名函数</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">Com2</span>(<span class="params">props</span>) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="language-xml"><span class="tag">&lt;<span class="name">MyCom</span> <span class="attr">onChange</span>=<span class="string">&#123;()</span> =&gt;</span> props.callback(props.id)&#125; /&gt;</span>  </span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 建议使用变量，避免内联对象</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">Com</span>(<span class="params">props</span>) &#123;</span><br><span class="line">    <span class="keyword">const</span> styles = &#123; <span class="attr">margin</span>: <span class="number">0</span> &#125;</span><br><span class="line">    <span class="keyword">const</span> prop = &#123; <span class="attr">name</span>: <span class="string">&#x27;lisy&#x27;</span> &#125;</span><br><span class="line">    <span class="comment">// return &lt;MyCom style=&#123;styles&#125; &#123;...prop&#125; /&gt;</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 可视区域加载</span></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">React</span> <span class="keyword">from</span> <span class="string">&quot;react&quot;</span>;</span><br><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">Button</span> &#125; <span class="keyword">from</span> <span class="string">&quot;antd&quot;</span>;</span><br><span class="line"><span class="keyword">import</span> <span class="title class_">LoadableVisibility</span> <span class="keyword">from</span> </span><br><span class="line"><span class="string">&quot;react-loadable-visibility/react-loadable&quot;</span>;</span><br><span class="line"><span class="keyword">const</span> <span class="title class_">MyComponent</span> = <span class="title class_">LoadableVisibility</span>(&#123;</span><br><span class="line">    <span class="attr">loader</span>: <span class="function">() =&gt;</span> <span class="title function_">import</span>(<span class="string">&quot;./MyComponent&quot;</span>),</span><br><span class="line">    <span class="attr">loading</span>: <span class="function">() =&gt;</span> <span class="language-xml"><span class="tag">&lt;<span class="name">div</span>&gt;</span>Loading...<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line">&#125;);</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">const</span> <span class="title function_">App</span> = (<span class="params"></span>) =&gt; &#123;</span><br><span class="line">    <span class="keyword">return</span> (</span><br><span class="line">        <span class="language-xml"><span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;<span class="name">h1</span>&gt;</span>My App<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;<span class="name">MyComponent</span> /&gt;</span></span></span><br><span class="line"><span class="language-xml">        <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line">    );</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// 交互式导入资源</span></span><br><span class="line"><span class="title function_">handleScrollToTop</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="title function_">import</span>(<span class="string">&#x27;react-scroll&#x27;</span>).<span class="title function_">then</span>(<span class="function"><span class="params">scroll</span> =&gt;</span> &#123;</span><br><span class="line">        scroll.<span class="property">animateScroll</span>.<span class="title function_">scrollToTop</span>(&#123;  &#125;)</span><br><span class="line">    &#125;)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>








    </div>

    
    
    <div>
      
        <div>
    
        <div style="text-align:center;color: #ccc;font-size:14px;margin-top:20px;">-------------本文结束<i class="fa fa-paw"></i>感谢您的阅读-------------</div>
    
</div>

      
    </div>
    
        

<div>
<ul class="post-copyright">
  <li class="post-copyright-author">
    <strong>本文作者： </strong>chuangges
  </li>
  <li class="post-copyright-link">
    <strong>本文链接：</strong>
    <a href="https://chuangges.gitee.io/2019/08/29/10-2-React%E5%B7%A5%E5%85%B7%E5%BA%93/" title="React 工具库">https://chuangges.gitee.io/2019/08/29/10-2-React工具库/</a>
  </li>
  <li class="post-copyright-license">
    <strong>版权声明： </strong>本博客所有文章除特别声明外，均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/zh_CN" rel="external nofollow noopener noreferrer" target="_blank"><i class="fab fa-fw fa-creative-commons"></i>BY-NC-SA</a> 许可协议。转载请注明出处！
  </li>
</ul>
</div>


      <footer class="post-footer">

        


        
    <div class="post-nav">
      <div class="post-nav-item">
    <a href="/2019/08/17/10-1-React%E6%A1%86%E6%9E%B6/" rel="prev" title="React 框架">
      <i class="fa fa-chevron-left"></i> React 框架
    </a></div>
      <div class="post-nav-item">
    <a href="/2019/11/03/11-1-typescript%20%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B/" rel="next" title="TypeScript 入门">
      TypeScript 入门 <i class="fa fa-chevron-right"></i>
    </a></div>
    </div>
      </footer>
    
  </article>
  
  
  



          </div>
          

<script>
  window.addEventListener('tabs:register', () => {
    let { activeClass } = CONFIG.comments;
    if (CONFIG.comments.storage) {
      activeClass = localStorage.getItem('comments_active') || activeClass;
    }
    if (activeClass) {
      let activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
      if (activeTab) {
        activeTab.click();
      }
    }
  });
  if (CONFIG.comments.storage) {
    window.addEventListener('tabs:click', event => {
      if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return;
      let commentClass = event.target.classList[1];
      localStorage.setItem('comments_active', commentClass);
    });
  }
</script>

        </div>
          
  
  <div class="toggle sidebar-toggle">
    <span class="toggle-line toggle-line-first"></span>
    <span class="toggle-line toggle-line-middle"></span>
    <span class="toggle-line toggle-line-last"></span>
  </div>

  <aside class="sidebar">
    <div class="sidebar-inner">

      <ul class="sidebar-nav motion-element">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <!--noindex-->
      <div class="post-toc-wrap sidebar-panel">
          <div class="post-toc motion-element"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#%E4%B8%80%E3%80%81React-Hooks"><span class="nav-number">1.</span> <span class="nav-text">一、React Hooks</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%95%B0%E6%8D%AE%E6%9B%B4%E6%96%B0%E9%A9%B1%E5%8A%A8"><span class="nav-number">1.1.</span> <span class="nav-text">数据更新驱动</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%89%A7%E8%A1%8C%E5%89%AF%E4%BD%9C%E7%94%A8"><span class="nav-number">1.2.</span> <span class="nav-text">执行副作用</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%8A%B6%E6%80%81%E8%8E%B7%E5%8F%96%E4%B8%8E%E4%BC%A0%E9%80%92"><span class="nav-number">1.3.</span> <span class="nav-text">状态获取与传递</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%8A%B6%E6%80%81%E6%B4%BE%E7%94%9F%E4%B8%8E%E4%BF%9D%E5%AD%98"><span class="nav-number">1.4.</span> <span class="nav-text">状态派生与保存</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%BC%80%E5%8F%91%E8%B0%83%E8%AF%95%E5%B7%A5%E5%85%B7"><span class="nav-number">1.5.</span> <span class="nav-text">开发调试工具</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E8%87%AA%E5%AE%9A%E4%B9%89-Hook"><span class="nav-number">1.6.</span> <span class="nav-text">自定义 Hook</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E4%BA%8C%E3%80%81%E7%BB%84%E4%BB%B6%E5%A4%8D%E7%94%A8%E6%96%B9%E6%A1%88"><span class="nav-number">2.</span> <span class="nav-text">二、组件复用方案</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#Mixin-%E6%B7%B7%E5%85%A5"><span class="nav-number">2.1.</span> <span class="nav-text">Mixin 混入</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#HOC-%E9%AB%98%E9%98%B6%E7%BB%84%E4%BB%B6"><span class="nav-number">2.2.</span> <span class="nav-text">HOC 高阶组件</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Render-Props"><span class="nav-number">2.3.</span> <span class="nav-text">Render Props</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#React-Hooks"><span class="nav-number">2.4.</span> <span class="nav-text">React Hooks</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E4%B8%89%E3%80%81%E7%BB%84%E4%BB%B6%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96"><span class="nav-number">3.</span> <span class="nav-text">三、组件性能优化</span></a></li></ol></div>
      </div>
      <!--/noindex-->

      <div class="site-overview-wrap sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
    <img class="site-author-image" itemprop="image" alt="chuangges" src="" data-original="/images/chuang.png">
  <p class="site-author-name" itemprop="name">chuangges</p>
  <div class="site-description" itemprop="description">chuangge's blog.</div>
</div>
<div class="site-state-wrap motion-element">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
          <a href="/archives/">
        
          <span class="site-state-item-count">39</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
            <a href="/categories/">
          
        <span class="site-state-item-count">7</span>
        <span class="site-state-item-name">分类</span></a>
      </div>
      <div class="site-state-item site-state-tags">
            <a href="/tags/">
          
        <span class="site-state-item-count">7</span>
        <span class="site-state-item-name">标签</span></a>
      </div>
  </nav>
</div>
  <div class="links-of-author motion-element">
      <span class="links-of-author-item">
        <a href="https://github.com/chuangges" title="GitHub → https:&#x2F;&#x2F;github.com&#x2F;chuangges" rel="external nofollow noopener noreferrer" target="_blank"><i class="fab fa-github fa-fw"></i>GitHub</a>
      </span>
      <span class="links-of-author-item">
        <a href="https://stackoverflow.com/yourname" title="StackOverflow → https:&#x2F;&#x2F;stackoverflow.com&#x2F;yourname" rel="external nofollow noopener noreferrer" target="_blank"><i class="fab fa-stack-overflow fa-fw"></i>StackOverflow</a>
      </span>
  </div>


  <div class="links-of-blogroll motion-element">
    <div class="links-of-blogroll-title"><i class="fa fa-link fa-fw"></i>
      友情链接
    </div>
    <ul class="links-of-blogroll-list">
        <li class="links-of-blogroll-item">
          <a href="https://juejin.im/" title="https:&#x2F;&#x2F;juejin.im&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">掘金</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://www.nowcoder.com/" title="https:&#x2F;&#x2F;www.nowcoder.com&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">牛客网</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://www.docschina.org/" title="https:&#x2F;&#x2F;www.docschina.org&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">印记中文</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="http://tool.lu/" title="http:&#x2F;&#x2F;tool.lu&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">在线工具</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://tinypng.com/" title="https:&#x2F;&#x2F;tinypng.com&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">图片压缩</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://bigjpg.com/" title="https:&#x2F;&#x2F;bigjpg.com&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">图片放大</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://tool.chinaz.com/" title="https:&#x2F;&#x2F;tool.chinaz.com&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">站长工具</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://learn-anything.xyz/" title="https:&#x2F;&#x2F;learn-anything.xyz&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">Learn-Anything</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://stackoverflow.com/" title="https:&#x2F;&#x2F;stackoverflow.com&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">Stack-Overflow</a>
        </li>
    </ul>
  </div>

      </div>

    </div>
  </aside>
  <div id="sidebar-dimmer"></div>


      </div>
    </main>

    <footer class="footer">
      <div class="footer-inner">
        

        

<div class="copyright">
  
  &copy; 
  <span itemprop="copyrightYear">2024</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">chuangge</span>
    <span class="post-meta-divider">|</span>
    <span class="post-meta-item-icon">
      <i class="fa fa-chart-area"></i>
    </span>
    <span title="站点总字数">1m</span>
    <span class="post-meta-divider">|</span>
    <span class="post-meta-item-icon">
      <i class="fa fa-coffee"></i>
    </span>
    <span title="站点阅读时长">15:14</span>
</div>
  <div class="powered-by">由 <a href="https://hexo.io/" class="theme-link" rel="external nofollow noopener noreferrer" target="_blank">Hexo</a> & <a href="https://pisces.theme-next.org/" class="theme-link" rel="external nofollow noopener noreferrer" target="_blank">NexT.Pisces</a> 强力驱动
  </div>

        








      </div>
    </footer>
  </div>

  
  <script src="/lib/anime.min.js"></script>
  <script src="/lib/velocity/velocity.min.js"></script>
  <script src="/lib/velocity/velocity.ui.min.js"></script>

<script src="/js/utils.js"></script>

<script src="/js/motion.js"></script>


<script src="/js/schemes/pisces.js"></script>


<script src="/js/next-boot.js"></script>




  















  

  

<script src="/live2dw/lib/L2Dwidget.min.js?094cbace49a39548bed64abff5988b05"></script><script>L2Dwidget.init({"pluginRootPath":"live2dw/","pluginJsPath":"lib/","pluginModelPath":"assets/","model":{"jsonPath":"/live2dw/assets/tororo.model.json"},"display":{"position":"left","width":180,"height":360},"mobile":{"show":false},"react":{"opacityDefault":1,"opacityOnHover":1},"log":false,"tagMode":false});</script>
        <style>
            [bg-lazy] {
                background-image: none !important;
                background-color: #eee !important;
            }
        </style>
        <script>
            window.imageLazyLoadSetting = {
                isSPA: false,
                preloadRatio: 1,
                processImages: null,
            };
        </script><script>window.addEventListener("load",function(){var t=/\.(gif|jpg|jpeg|tiff|png)$/i,r=/^data:image\/[a-z]+;base64,/;Array.prototype.slice.call(document.querySelectorAll("img[data-original]")).forEach(function(a){var e=a.parentNode;"A"===e.tagName&&(e.href.match(t)||e.href.match(r))&&(e.href=a.dataset.original)})});</script><script>!function(e){e.imageLazyLoadSetting.processImages=t;var n=e.imageLazyLoadSetting.isSPA,i=e.imageLazyLoadSetting.preloadRatio||1,r=o();function o(){var t=Array.prototype.slice.call(document.querySelectorAll("img[data-original]")),e=Array.prototype.slice.call(document.querySelectorAll("[bg-lazy]"));return t.concat(e)}function t(){n&&(r=o());for(var t,a=0;a<r.length;a++)0<=(t=(t=r[a]).getBoundingClientRect()).bottom&&0<=t.left&&t.top<=(e.innerHeight*i||document.documentElement.clientHeight*i)&&function(){var t,e,n,i,o=r[a];e=function(){r=r.filter(function(t){return o!==t})},(t=o).hasAttribute("bg-lazy")?(t.removeAttribute("bg-lazy"),e&&e()):(n=new Image,i=t.getAttribute("data-original"),n.onload=function(){t.src=i,t.removeAttribute("data-original"),e&&e()},t.src!==i&&(n.src=i))}()}function a(){clearTimeout(t.tId),t.tId=setTimeout(t,500)}t(),document.addEventListener("scroll",a),e.addEventListener("resize",a),e.addEventListener("orientationchange",a)}(this);</script></body>
</html>
